

#include "atomic_op_asm.h"

#if defined(_ARM_ARCH_6)
/*
 * ARMv6 has load-exclusive/store-exclusive which works for both user
 * and kernel.
 */
ENTRY_NP(_atomic_cas_32)
	mov	ip, r0			/* we need r0 for return value */
1:
	ldrex	r0, [ip]		/* load old value */
	cmp	r0, r1			/*   compare? */
#ifdef __thumb__
	bne	2f			/*     return if different */
#else
	RETc(ne)			/*     return if different */
#endif
	strex	r3, r2, [ip]		/* store new value */
	cmp	r3, #0			/*   succeed? */
	bne	1b			/*     nope, try again. */
#ifdef _ARM_ARCH_7
	dsb
#else
	mcr	p15, 0, r3, c7, c10, 4	/* data synchronization barrier */
#endif
2:	RET				/* return. */
END(_atomic_cas_32)

ATOMIC_OP_ALIAS(atomic_cas_32,_atomic_cas_32)
ATOMIC_OP_ALIAS(atomic_cas_uint,_atomic_cas_32)
ATOMIC_OP_ALIAS(atomic_cas_ulong,_atomic_cas_32)
ATOMIC_OP_ALIAS(atomic_cas_ptr,_atomic_cas_32)
ATOMIC_OP_ALIAS(atomic_cas_32_ni,_atomic_cas_32)
ATOMIC_OP_ALIAS(atomic_cas_uint_ni,_atomic_cas_32)
ATOMIC_OP_ALIAS(atomic_cas_ulong_ni,_atomic_cas_32)
ATOMIC_OP_ALIAS(atomic_cas_ptr_ni,_atomic_cas_32)
CRT_ALIAS(__sync_val_compare_and_swap_4,_atomic_cas_32)
STRONG_ALIAS(_atomic_cas_uint,_atomic_cas_32)
STRONG_ALIAS(_atomic_cas_ulong,_atomic_cas_32)
STRONG_ALIAS(_atomic_cas_32_ni,_atomic_cas_32)
STRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_32)
STRONG_ALIAS(_atomic_cas_uint_ni,_atomic_cas_32)
STRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_32)
STRONG_ALIAS(_atomic_cas_ptr,_atomic_cas_32)

#endif /* _ARM_ARCH_6 */
